package za.org.jcicada.nodeproxy.impl;

import java.io.IOException;
import java.net.URI;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import za.org.jcicada.genss.SystemURN;
import za.org.jcicada.genss.lifecycle.ILifeCycleServer;
import za.org.jcicada.genss.lifecycle.LogLevel;
import za.org.jcicada.genss.lifecycle.ILifeCycleServer.Shutdown;
import za.org.jcicada.genss.messages.Result;
import za.org.jcicada.genss.messages.SuccessCode;

public class NodeSystem implements ILifeCycleServer.ICallback {
	
    /** Logger object used for logging messages. */
    private static final Log logger = LogFactory.getLog(NodeSystem.class);

    ProcessBuilder processBuilder;
	Process process;
	Thread sinkThread;
	String className;
	
	public NodeSystem(String className, SystemURN systemURN, URI uriCfgMngrLocation) throws ClassNotFoundException {
		this.className = className;
		Class.forName(className);
		processBuilder = new ProcessBuilder("java", "-classpath", System.getProperties().getProperty("java.class.path"), className, systemURN.getSystemName(), uriCfgMngrLocation.toString());
		processBuilder.redirectErrorStream(true);
	}
	
	public void initialize() throws IOException {
		process = processBuilder.start();
		sinkThread = new Thread(new Runnable() {

			public void run() {
				byte[] buffer = new byte[1024];
				try {
					while (process.getInputStream().read(buffer) != -1);
					process.getInputStream().close();
				} catch (IOException e) {
					// stream has been closed so terminate
				}
			}
			
		}, "SinkThread-" + className);
		sinkThread.start();
	}
	
	public Result reconnect() {
		return new Result(SuccessCode.COMPLETE_FAILURE, "Can't reconnect through NodeProxy");
	}

	public Result setLogLevel(LogLevel level) {
		return new Result(SuccessCode.COMPLETE_FAILURE, "Can't set log level through NodeProxy");
	}

	public Result shutdown(Shutdown behaviour) {
		process.destroy();
		try {
			process.waitFor();
		} catch (InterruptedException e) {
			logger.error(e);
			return new Result(SuccessCode.COMPLETE_FAILURE, e.getMessage());
		}
		int exitValue = process.exitValue();
		process = null;
		if (behaviour == Shutdown.RESTART) {
			try {
				initialize();
			} catch (IOException e) {
				logger.error(e);
				return new Result(SuccessCode.PARTIAL_SUCCESS, e.getMessage());
			}
		}
		return new Result(exitValue == 0? SuccessCode.COMPLETE_SUCCESS: SuccessCode.PARTIAL_SUCCESS, String.format("Exit value = %d", exitValue));
	}
	
	public Result ping() {
		return new Result(SuccessCode.COMPLETE_FAILURE, "Can't ping through NodeProxy");
	}

}
